//
// Created by liugang on 9/17/25.
//
#include <iostream>

#include "nodes.h"
#include "vars.h"

namespace test1 {

struct Model {
};

struct Instance {
    Model* model;

    real K1{1};
    real K2{1};
    real R{1};

    real index{0};
    real t2{0};

    auto show_all() -> void {
        fprintf(stdout, "%p inst->K1 = %lf\n", &K1, K1);
        fprintf(stdout, "%p inst->K2 = %lf\n", &K2, K2);
        fprintf(stdout, "%p inst->R = %lf\n", &R, R);
        fprintf(stdout, "%p inst->index = %lf\n", &index, index);
        fprintf(stdout, "%p inst->t2 = %lf\n", &t2, t2);
    }
};

enum LOC_ID : int32_t {
    LOCID_M,
    LOCID_N,
    LOCID_A,
    LOCID_B,
    LOCID_P,
    LOCID_Q,
};

/**
 * 简化处理，避免demo搞得过于复杂
 */
struct Context {
    Instance* inst;
};


/**
 * 简化处理，避免demo搞得过于复杂
 */
auto AccessV(void* c, int32_t loc_id) -> real {
    Context* ctx = static_cast<Context*>(c);
    return 1;
}

auto AccessI(void* c, int32_t loc_id) -> real {
    Context* ctx = static_cast<Context*>(c);
    return 1;
}

auto test() -> void {
    Model vModel;
    Instance vInstance;

    Model* model = &vModel;
    Instance* inst = &vInstance;

    FLOW flow;

    // 流程编排阶段，inst 和 model 就已经创建好了
    flow.bind_target(inst, model);

    // 注册本 flow 的 access 函数
    auto V = flow.access("V", AccessV);
    auto I = flow.access("I", AccessI);

    // 定义求导变量
    auto Va = flow.var("V(a)", V(LOCID_A));
    auto Vb = flow.var("V(b)", V(LOCID_B));
    auto Vp = flow.var("V(p)", V(LOCID_P));
    auto Vq = flow.var("V(q)", V(LOCID_Q));
    auto Vm = flow.var("V(m)", V(LOCID_M));
    auto Vn = flow.var("V(n)", V(LOCID_N));

    // 定义计算流程
    // clang-format off
    flow //
    .FOR(ref(inst->index) = 0.0, ref(inst->index) < 10.0, ref(inst->index) = ref(inst->index) + 1.0)
        .IF(Vm > Vn)
            .EXPR(ref(inst->t2) = (Va - Vb) / ref(inst->R) + ref(inst->K1) - ref(inst->index))
            .BREAK()
        .ELSE()
            //.EXPR(ref(inst->t2) = (Vp - Vq) / ref(inst->R) + ref(inst->K2) + ref(inst->index))
            .EXPR(ref(inst->t2) = ref(inst->t2) + ref(inst->index))
            .CONTINUE()
        .ENDIF()
    .ENDFOR()
    .COMMIT()
    ;
    // clang-format on

    // 将语法树打印出来看下效果
    print_node(flow.root(), 0, PF_PRINTCHILDREN, stdout);

    // 执行时：
    Context context{inst}; // NOTICE：Context 在执行时才是有效的
    flow.bind_context(&context);

    eval_stmt(&flow, flow.root());

    inst->show_all();
}

}